﻿
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using TotalApplication.Core;

namespace TotalApplication.AngelSix
{
    /// <summary>
    /// A base page for all pages to gain base functionality from.
    /// </summary>
    public class BasePage : UserControl
    {

        #region Private member

        private object? _viewModel;

        #endregion

        #region  Public properties [custom animation & anime seconds & viewModels]

        /// <summary>
        /// BaseViewModel object for the page
        /// </summary>
        public object ViewModelObject
        {
            get { return _viewModel ?? new BaseViewModel(); }
            set
            {
                if (_viewModel == value) return;

                _viewModel = value;

                // On view model changed
                OnViewModelChanged();

                DataContext = _viewModel;
            }
        }

        public PageAnimation PageLoadAnimation { get; set; } = PageAnimation.SlidAndFadeInFromRight;

        public PageAnimation PageUnLoadAnimation { get; set; } = PageAnimation.SlidAndFadeOutToLeft;

        public float SlideSeconds { get; set; } = 0.4f;

        public bool ShouldAnimateOut { get; set; } = false;

        #endregion

        #region Constructor [Initial events : loaded & new viewModel & animation type judge]

        public BasePage()
        {
            // Void Loaded Animation At Design Mode
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                return;
            }

            if (this.PageLoadAnimation == PageAnimation.None)
            {
                this.Visibility = Visibility.Collapsed;
            }
            this.Loaded += BasePage_Loaded;
        }


        #endregion

        #region Animation load/unload & custom loaded event [Base_Loaded event]
        private async void BasePage_Loaded(object sender, RoutedEventArgs e)
        {
            if (ShouldAnimateOut)
                // Animate the page out
                await AnimateOut();
            // Other else,,,
            else
                // Animate the page in
                await AnimateIn();
        }

        public async Task AnimateOut()
        {
            // judge conditions
            if (this.PageUnLoadAnimation == PageAnimation.None)
            {
                return;
            }

            switch (this.PageUnLoadAnimation)
            {
                case PageAnimation.SlidAndFadeOutToLeft:
                    // Implement slide and fade out to left animation
                    await this.SlideAndFadeOutToLeftAsync(this.SlideSeconds, width: Application.Current.MainWindow.ActualWidth);

                    break;
                default:
                    throw new NotImplementedException($"Animation {this.PageLoadAnimation} is not implemented.");
            }
        }

        public async Task AnimateIn()
        {
            if (this.PageLoadAnimation == PageAnimation.None)
            {
                return;
            }

            switch (this.PageLoadAnimation)
            {
                case PageAnimation.SlidAndFadeInFromRight:
                    // Implement slide and fade in from right animation
                    await this.SlideAndFadeInFromRightAsync(this.SlideSeconds, width: Application.Current.MainWindow.ActualWidth);

                    break;
                case PageAnimation.SlidAndFadeOutToLeft:
                    // Implement slide and fade out to left animation
                    break;
                default:
                    throw new NotImplementedException($"Animation {this.PageLoadAnimation} is not implemented.");
            }
        }

        #endregion

        #region ViewModel Changed Events

        /// <summary>
        /// Fired when the view model is changed
        /// </summary>
        protected virtual void OnViewModelChanged()
        {

        }

        #endregion
    }

    /// <summary>
    /// A base page with added ViewModel support
    /// </summary>
    public class BasePage<VM> : BasePage
        where VM : BaseViewModel, new()
    {
        #region  Public properties 

        public VM ViewModel
        {
            get { return (VM)ViewModelObject; }
            set { ViewModelObject = value; }
        }
        #endregion

        #region Constructor 

        public BasePage(VM? specificViewModel = null) : base()
        {
            if (specificViewModel != null)
                this.ViewModel = specificViewModel;
            else
                // 即便没有初始化VM，容器也会自动生成一个
                this.ViewModel = IoC.Get<VM>();
        }


        #endregion
    }
}
